/*
 * @file	sensor_support.h
 * @autohr  Queclink beck.wan
 * @date	2019年4月13日
 * @brief
 *
 * Coypright (C) 2017 Queclink Co., Ltd. All Rights Reserved
 *
 * @attention
 *
 * @usage
 *
 * @record
 *
 */

#ifndef __SENSOR_SUPPORT_H__
#define __SENSOR_SUPPORT_H__



#ifndef _SSIZE_T
#define _SSIZE_T
typedef signed int ssize_t;
#endif



#ifdef __cplusplus
extern "C" {
#endif

/* 加速度值, 单位与测量量程(QLSDK_SENSOR_ACC_RANGE)及位数有关:
 * 12bit: BMA253
 *   ±2g: 0.98mg;
 *   ±4g: 1.95mg;
 *   ±8g: 3.94mg;
 *   ±16g: 7.81mg.
 * 16bit: BMI160
 *   ±2g: 0.061mg;
 *   ±4g: 0.122mg;
 *   ±8g: 0.244mg;
 *   ±16g: 0.488mg. */
struct acceleration {
    signed short    x;  /* X轴 */
	signed short    y;  /* Y轴 */
	signed short    z;  /* Z轴 */
};

/* 单位为 mg 的加速度值 */
struct acceleration_mg {
    float   x;  /* X轴 */
	float   y;  /* Y轴 */
    float   z;  /* Z轴 */
};

/* 角速度值(angular rate), 单位与测量量程(QLSDK_SENSOR_GYRO_RANGE)及位数有关:
 * 16bit: BMI160
 *   ±125dps: 3.8mdps(毫度每秒);
 *   ±250dps: 7.6mdps;
 *   ±500dps: 15.3mdps;
 *   ±1000dps: 30.5mdps;
 *   ±2000dps: 61.0mdps. */
struct angularrate {
    signed short    x;  /* X轴 */
	signed short    y;  /* Y轴 */
	signed short    z;  /* Z轴 */
};


typedef struct {
    unsigned int  count;
    struct acceleration *frame;
} accel_frames_t;

typedef struct {
    unsigned int count;
    struct angularrate *frame;
} gyro_frames_t;

typedef struct {
    /*
     * @brief  sensor芯片探测
     * @retval true:成功, false:失败
     */
    bool    (*const probe)(void);
    /*
     * @brief  sensor申请内存/寄存器配置配置,内部接口
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const initialize)(void);
    /*
     * @brief  sensor进入低功耗配置，内部接口
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const lowpower)(void);
    /*
     * @brief  读取sensor ID，内部接口
     * @param  芯片ID
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const chip_id)(void *);
    /*
     * @brief  读取sensor 温度值，内部接口
     * @retval 非负数为温度值, others:错误码(硬件故障/通信异常)
     */
    float   (*const temperature)(void);
    /*
     * @brief  读取一帧accel原始值，内部接口
     * @param  数据类型为 accel_frame_t
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const accel_frame_get)(void *);
    /*
     * @brief  读取一帧gyro原始值，内部接口
     * @param  BMA253不支持，BMI160支持
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const gyro_frame_get)(void *);
    /*
     * @brief  读取SENSOR FIFO数据，内部接口
     * @param  acc_frames读取的多帧ACC值，gyro_frames读取的多帧GYRO值
     * @retval 0:成功, others:错误码(硬件故障/通信异常)
     */
    int     (*const read_fifo_data)(accel_frames_t *accel_data, gyro_frames_t *gyro_data);
    /*
     * @brief  获取ACC最大值(与adc bit数有关)，内部接口
     * @retval ACC最大值
     */
    unsigned int    (*const max_accel_value)(void);

    /*
     * @brief  获取设备真实采样率,可以为NULL,表示与SDK配置的一致
     * @retval 真实采样率,单位Hz
     */
    double  (*const odr_get)(void);

    /*
     * @brief  获取GYRO最大值(与adc bit数有关)，内部接口,为NULL表示与ACC最大值一致
     * @retval GYRO最大值
     */
    unsigned int    (*const max_gyro_value)(void);

} sensor_function_t;


/*
 * SENSOR 硬件适配接口
 * 请定义 QLSDK_SENSOR_OPS_PTR 宏进行适配;
 * 为简化软件设计, 总是只使用 INT1 中断, 不使用 INT2 中断.
 */
struct sensor_ops {
    uint8_t is_spi; /* interface type, i2c : 0, spi : 1 */
    struct {
    void    (*select)(void);                /* access enable */
    void    (*deselect)(void);              /* access disable */
    ssize_t (*write)(const void *, size_t); /* write to sensor */
    ssize_t (*read)(void *, size_t);        /* read from sensor */
    } spi;


    /*
     * @brief  打开 INT1 中断
     * @note   固定使用"上升沿"触发中断.
     * @param  isr: [I], 中断服务程序, 请将该ISR注册到 INT1 中断服务程序中;
     *         ptr: [I], 中断服务程序 isr 使用的 ptr.
     * @retval none
     */
    void    (*int1_enable)(void (*isr)(void *ptr), void *ptr);
    /*
     * @brief  关闭 INT1 中断
     */
    void    (*int1_disable)(void);

    /*
     * @brief  其它进入睡眠模式的条件
     * @note   为了降低产品功耗, 原则上当设备静止时, sensor 需进入 sleep 模式,
     *         并使能 INT1 中断, 待达到运动阈值时, sensor 再唤醒并触发 INT1 中断,
     *         以便降低 sensor 的功耗; 但考虑到 sensor 判断"静止"的准确性, 以及某些
     *         场景下(比如行驶途中) sensor 不应自动进入 sleep 模式, 故增加此接口,
     *         用户可以利用该接口干预 sensor 的睡眠.
     * @retval true:静止时进入sleep模式, false:不可以进入sleep模式.
     */
    bool    (*extra_sleep_en)(void);
};


extern const sensor_function_t *hal_snsr_func;

extern const struct qltask_snsr_ops_t qlsdk_sensor_ops_func;

typedef struct {
    bool                    chip_valid;
    bool                    gyro_use;
    bool                    range_check;
    unsigned int            reset_tick;
    unsigned int            self_check;
    unsigned char           accel_range;
    unsigned short          gyro_range;
    unsigned short          cur_odr;
    unsigned short          new_odr;
    struct acceleration_mg  zero_offset;
    int                     lwp_check_time;
} snsr_support_t;

extern snsr_support_t qlsdk_sensor_support;


/* 存储ACC量程配置 */
void sensor_accel_range_set(unsigned char range);

/* 存储GYRO量程配置 */
void sensor_gyro_range_set(unsigned short range);

/* 配置SENSOR采样率 */
int sensor_accel_odr_set(unsigned short odr);

/* 获取1G表示的ACC值,供senosr中间层使用 */
int sensor_accel_1g_range_count(void);

/* 配置零偏校准参数 */
int sensor_zero_offset_set(float x, float y, float z);


/* 配置自检间隔（低功耗模式下） */
int sensor_lwp_check_time_set(int time);

int sensor_gyro_1dge_per_s_range_count(void);

/// @brief sensor初始化
/// @param none
/// @return 
int sensor_initial(void);


int sensor_spi_read_reg(unsigned int addr, unsigned char addr_len, unsigned char *data, unsigned int len);
int sensor_spi_write_reg(unsigned int addr, unsigned char addr_len, unsigned char *data, unsigned int len);


/**
 * @brief 初始化
 */
void sensor_initialize(void);

/**
 * @brief 低功耗初始化
 */
void sensor_lowpower_initialize(void);
#ifdef __cplusplus
}
#endif

#endif /* __SENSOR_SUPPORT_H__ */
